
#include	<stdlib.h>
#include	<math.h>

#ifdef __APPLE__
        #include <GLUT/glut.h>
        #include <OpenGL/gl.h>
        #include <OpenGL/glu.h>
#else
        #include <GL/glut.h>
        #include <GL/gl.h>
        #include <GL/glu.h>
#endif

void drawCube(float size, float cubeTranslation[])
{ 
	glPushMatrix();
		glTranslatef(cubeTranslation[0], cubeTranslation[1], cubeTranslation[2]);

		/* We tell we want to draw quads */
		glColor3f(   1.0,  1.0, 1.0 );

		// White side - BACK
		glBegin(GL_LINE_LOOP);
		glVertex3f(  size*0.1, -size*0.1, size*0.1 );
		glVertex3f(  size*0.1,  size*0.1, size*0.1 );
		glVertex3f( -size*0.1,  size*0.1, size*0.1 );
		glVertex3f( -size*0.1, -size*0.1, size*0.1 );
		glEnd();

		 // White side - BACK
		glBegin(GL_LINE_LOOP);
		glVertex3f(  size*0.1, -size*0.1, size*0.1 );
		glVertex3f(  size*0.1,  size*0.1, size*0.1 );
		glVertex3f( -size*0.1,  size*0.1, size*0.1 );
		glVertex3f( -size*0.1, -size*0.1, size*0.1 );
		glEnd();
		 
		// Purple side - RIGHT
		glBegin(GL_LINE_LOOP);
		glVertex3f( size*0.1, -size*0.1, -size*0.1 );
		glVertex3f( size*0.1,  size*0.1, -size*0.1 );
		glVertex3f( size*0.1,  size*0.1,  size*0.1 );
		glVertex3f( size*0.1, -size*0.1,  size*0.1 );
		glEnd();
		 
		// Green side - LEFT
		glBegin(GL_LINE_LOOP);
		glVertex3f( -size*0.1, -size*0.1,  size*0.1 );
		glVertex3f( -size*0.1,  size*0.1,  size*0.1 );
		glVertex3f( -size*0.1,  size*0.1, -size*0.1 );
		glVertex3f( -size*0.1, -size*0.1, -size*0.1 );
		glEnd();
		 
		// Blue side - TOP
		glBegin(GL_LINE_LOOP);
		glVertex3f(  size*0.1,  size*0.1,  size*0.1 );
		glVertex3f(  size*0.1,  size*0.1, -size*0.1 );
		glVertex3f( -size*0.1,  size*0.1, -size*0.1 );
		glVertex3f( -size*0.1,  size*0.1,  size*0.1 );
		glEnd();
		 
		// Red side - BOTTOM
		glBegin(GL_LINE_LOOP);
		glVertex3f(  size*0.1, -size*0.1, -size*0.1 );
		glVertex3f(  size*0.1, -size*0.1,  size*0.1 );
		glVertex3f( -size*0.1, -size*0.1,  size*0.1 );
		glVertex3f( -size*0.1, -size*0.1, -size*0.1 );
		glEnd();

		// Purple side - RIGHT
		glBegin(GL_LINE_LOOP);
		glVertex3f( size*0.1, -size*0.1, -size*0.1 );
		glVertex3f( size*0.1,  size*0.1, -size*0.1 );
		glVertex3f( size*0.1,  size*0.1,  size*0.1 );
		glVertex3f( size*0.1, -size*0.1,  size*0.1 );
		glEnd();
		 
		// Green side - LEFT
		glBegin(GL_LINE_LOOP);
		glVertex3f( -size*0.1, -size*0.1,  size*0.1 );
		glVertex3f( -size*0.1,  size*0.1,  size*0.1 );
		glVertex3f( -size*0.1,  size*0.1, -size*0.1 );
		glVertex3f( -size*0.1, -size*0.1, -size*0.1 );
		glEnd();
		 
		// Blue side - TOP
		glBegin(GL_LINE_LOOP);
		glVertex3f(  size*0.1,  size*0.1,  size*0.1 );
		glVertex3f(  size*0.1,  size*0.1, -size*0.1 );
		glVertex3f( -size*0.1,  size*0.1, -size*0.1 );
		glVertex3f( -size*0.1,  size*0.1,  size*0.1 );
		glEnd();
		 
		// Red side - BOTTOM
		glBegin(GL_LINE_LOOP);
		glVertex3f(  size*0.1, -size*0.1, -size*0.1 );
		glVertex3f(  size*0.1, -size*0.1,  size*0.1 );
		glVertex3f( -size*0.1, -size*0.1,  size*0.1 );
		glVertex3f( -size*0.1, -size*0.1, -size*0.1 );
		glEnd();
	glPopMatrix();
}

/*
** Function called to update rendering
*/
float bigCubePos[3] = {0,0,0}, cubeOnePos[3] = {0.1f,0,0}, cubeTwoPos[3] = {-0.1f,0,0};
float bigCubeSize = 5.0f, littleCubeSize = 0.5f;

void		DisplayFunc(void)
{
  static float alpha = 0;

  /* Clear the buffer, clear the matrix */
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  glRotatef(30, 1, 0, 0);
  glRotatef(30, 0, 1, 0);

	drawCube(bigCubeSize, bigCubePos);
 	drawCube(littleCubeSize, cubeOnePos);
	drawCube(littleCubeSize, cubeTwoPos);

	// collision
	for (int i = 0; i < 3; ++i)
	{
		if (cubeOnePos[i] > bigCubeSize)
			cubeOnePos[i] = bigCubeSize;
		if (cubeTwoPos[i] > bigCubeSize)
			cubeTwoPos[i] = bigCubeSize;

		if (cubeOnePos[i] < -bigCubeSize)
			cubeOnePos[i] = -bigCubeSize;
		if (cubeTwoPos[i] < -bigCubeSize)
			cubeTwoPos[i] = -bigCubeSize;
			
	}

  /* End */
  glFlush();
  glutSwapBuffers();

  /* Update again and again */
  glutPostRedisplay();
  glMatrixMode(GL_PROJECTION);
}

/*
** Function called when the window is created or resized
*/
void		ReshapeFunc(int width, int height)
{
  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();
  glViewport(0, 0, width, height);

  glMatrixMode(GL_MODELVIEW);
  glutPostRedisplay();
}

/*
** Function called when a key is hit
*/
void		KeyboardFunc(unsigned char key, int x, int y)
{
  int foo;

  foo = x + y; /* Has no effect: just to avoid a warning */
  if ('q' == key || 'Q' == key || 27 == key)
      exit(0);
	// cube one
	else if ('a' == key)
			cubeOnePos[0] += 0.1f;
	else if ('s' == key)
			cubeOnePos[1] += 0.1f;
	else if ('d' == key)
			cubeOnePos[2] += 0.1f;
	else if ('z' == key)
			cubeOnePos[0] -= 0.1f;
	else if ('x' == key)
			cubeOnePos[1] -= 0.1f;
	else if ('c' == key)
			cubeOnePos[2] -= 0.1f;
	// cube two
	else if ('f' == key)
			cubeTwoPos[0] += 0.1f;
	else if ('g' == key)
			cubeTwoPos[1] += 0.1f;
	else if ('h' == key)
			cubeTwoPos[2] += 0.1f;
	else if ('v' == key)
			cubeTwoPos[0] -= 0.1f;
	else if ('b' == key)
			cubeTwoPos[1] -= 0.1f;
	else if ('n' == key)
			cubeTwoPos[2] -= 0.1f;

}


int	main(int argc, char **argv)
{
  /* Creation of the window */
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  glutInitWindowSize(1024, 1024);
  glutCreateWindow("Spinning cube");

  /* OpenGL settings */
  glClearColor(0, 0, 0, 0);
  glEnable(GL_DEPTH_TEST);

  /* Declaration of the callbacks */
  glutDisplayFunc(&DisplayFunc);
  glutReshapeFunc(&ReshapeFunc);
  glutKeyboardFunc(&KeyboardFunc);

  /* Loop */
  glutMainLoop();

  return 0;
}

/* ========================================================================= */
